﻿#include "expressionparser.h"
#include <functional>
#include <stdexcept>
#include <cctype>

using namespace std;

elementType ExpressionParser::parse() {
    pos = 0;
    return parseExpression();
}

function<elementType(elementType, elementType)> ExpressionParser::getFunction() {
    return [this](elementType a, elementType b) {
        this->pos = 0;
        this->a = a;
        this->b = b;
        return parseExpression();
    };
}

elementType ExpressionParser::parseExpression() {
    elementType result = parseTerm();
    while (pos < expr.size()) {
        if (expr[pos] == '+') {
            pos++;
            result += parseTerm();
        } else if (expr[pos] == '-') {
            pos++;
            result -= parseTerm();
        } else {
            break;
        }
    }
    return result;
}

elementType ExpressionParser::parseTerm() {
    elementType result = parseFactor();
    while (pos < expr.size()) {
        if (expr[pos] == '*') {
            pos++;
            result *= parseFactor();
        } else if (expr[pos] == '/') {
            pos++;
            result /= parseFactor();
        } else if (expr[pos] == '%') {
            pos++;
            result %= parseFactor();
        } else {
            break;
        }
    }
    return result;
}

elementType ExpressionParser::parseFactor() {
    if (pos >= expr.size()) {
        throw runtime_error("Unexpected end of expression");
    }
    if (expr[pos] == 'a') {
        pos++;
        return a;
    } else if (expr[pos] == 'b') {
        pos++;
        return b;
    } else if (isdigit(expr[pos]) || expr[pos] == '-') {
        size_t startPos = pos;
        if (expr[pos] == '-') pos++;
        while (pos < expr.size() && isdigit(expr[pos])) pos++;
        return stoi(expr.substr(startPos, pos - startPos));
    } else if (expr[pos] == '(') {
        pos++;
        elementType result = parseExpression();
        if (expr[pos] != ')') {
            throw runtime_error("Mismatched parentheses");
        }
        pos++;
        return result;
    } else {
        throw runtime_error("Unexpected character in expression");
    }
}


void ExpressionParser::setExpr(const string &expression) {
        expr = expression;
    }
